home *** CD-ROM | disk | FTP | other *** search
-
- /* MODULE HTVMSUtil.c
- ** VMS Utility Routines
- **
- ** AUTHORS:
- ** MD Mark Donszelmann duns@vxdeop.cern.ch
- **
- ** HISTORY:
- ** 14 Nov 93 MD Written
- **
- ** BUGS:
- **
- **
- */
-
- #include "HTUtils.h"
- #include "tcp.h"
- #include "HTFormat.h"
- #include "HTStream.h"
- #include "HTVMSUtils.h"
- /*#include <stdio.h> included by HTUtils.h -- FM */
- /*#include <unixlib.h> included by HTUtils.h -- FM */
- #include <ssdef.h>
- #include <jpidef.h>
- #include <prvdef.h>
- #include <acldef.h>
- #include <chpdef.h>
- #include <descrip.h>
- #include <lib$routines.h>
- #include <starlet.h>
- #include <rmsdef.h>
-
- #include "LYLeaks.h"
-
- #define INFINITY 512 /* File name length @@ FIXME */
-
- PUBLIC BOOL HTVMSFileVersions=FALSE; /* Include version numbers in listing? */
-
- typedef struct {
- unsigned long BufferLength : 16;
- unsigned long ItemCode : 16;
- unsigned long BufferAddress : 32;
- unsigned long ReturnLengthAddress : 32;
- } ItemStruct;
-
- extern CONST char * HTHostName NOPARAMS;
-
- /* PUBLIC HTVMS_authSysPrv()
- ** CHECKS IF THIS PROCESS IS AUTHORIZED TO ENABLE SYSPRV
- ** ON ENTRY:
- ** No arguments.
- **
- ** ON EXIT:
- ** returns YES if SYSPRV is authorized
- */
- PUBLIC BOOL HTVMS_authSysPrv NOARGS
- {
- unsigned long Result;
- ItemStruct ItemList[2];
- unsigned long Length;
- unsigned long Buffer[2];
-
- /* fill Item */
- ItemList[0].BufferLength = sizeof(Buffer);
- ItemList[0].BufferAddress = (unsigned long)Buffer;
- ItemList[0].ReturnLengthAddress = (unsigned long)&Length;
- ItemList[0].ItemCode = JPI$_AUTHPRIV;
-
- /* terminate list */
- ItemList[1].ItemCode = 0;
- ItemList[1].BufferLength = 0;
-
- /* call system */
- Result = sys$getjpiw(0, 0, 0, ItemList, 0, 0, 0);
-
- if (Result != SS$_NORMAL)
- return(NO);
-
- if (Buffer[0] & PRV$M_SYSPRV)
- return(YES);
-
- return(NO);
- }
-
-
-
- /* PUBLIC HTVMS_enableSysPrv()
- ** ENABLES SYSPRV
- ** ON ENTRY:
- ** No arguments.
- **
- ** ON EXIT:
- **
- */
- PUBLIC void HTVMS_enableSysPrv NOARGS
- {
- unsigned long Result;
- unsigned long Prv[2], PreviousPrv[2];
-
- Prv[0] = PRV$M_SYSPRV;
- Prv[1] = 0;
- Result = sys$setprv(1,&Prv,0,&PreviousPrv);
-
- if (TRACE) {
- if (Result == SS$_NORMAL) {
- if (!(PreviousPrv[0] & PRV$M_SYSPRV)) {
- fprintf(stderr, "HTVMS_enableSysPrv: Enabled SYSPRV\n");
- }
- }
- }
- }
-
-
-
- /* PUBLIC HTVMS_disableSysPrv()
- ** DISABLES SYSPRV
- ** ON ENTRY:
- ** No arguments.
- **
- ** ON EXIT:
- **
- */
- PUBLIC void HTVMS_disableSysPrv NOARGS
- {
- unsigned long Result;
- unsigned long Prv[2], PreviousPrv[2];
-
- Prv[0] = PRV$M_SYSPRV;
- Prv[1] = 0;
- Result = sys$setprv(0,&Prv,0,&PreviousPrv);
-
- if (TRACE) {
- if (Result == SS$_NORMAL) {
- if (PreviousPrv[0] & PRV$M_SYSPRV) {
- fprintf(stderr, "HTVMS_disableSysPrv: Disabled SYSPRV\n");
- }
- }
- }
- }
-
-
-
- /* PUBLIC HTVMS_checkAccess()
- ** CHECKS ACCESS TO FILE FOR CERTAIN USER
- ** ON ENTRY:
- ** FileName The file to be accessed
- ** UserName Name of the user to check access for.
- ** User nobody, represented by "" is given NO for an answer
- ** Method Name of the method to be chceked
- **
- ** ON EXIT:
- ** returns YES if access is allowed
- **
- */
- PUBLIC BOOL HTVMS_checkAccess ARGS3(
- CONST char *, FileName,
- CONST char *, UserName,
- CONST char *, Method)
- {
- unsigned long Result;
- ItemStruct ItemList[2];
- unsigned long Length;
- unsigned long Buffer;
- unsigned long ObjType;
-
- char *VmsName;
-
- struct dsc$descriptor_s FileNameDesc;
- struct dsc$descriptor_s UserNameDesc;
-
- char *colon;
-
- /* user nobody should access as from account under which server is running */
- if (0 == strcmp(UserName,""))
- return(NO);
-
- /* check Filename and convert */
- colon = strchr(FileName,':');
- if (colon)
- VmsName = HTVMS_name("",colon+1);
- else
- VmsName = HTVMS_name("",FileName);
-
- /* check for GET */
- if (0 == strcmp(Method,"GET"))
- {
- /* fill Item */
- ItemList[0].BufferLength = sizeof(Buffer);
- ItemList[0].BufferAddress = (unsigned long)&Buffer;
- ItemList[0].ReturnLengthAddress = (unsigned long)&Length;
- ItemList[0].ItemCode = CHP$_FLAGS;
-
- /* terminate list */
- ItemList[1].ItemCode = 0;
- ItemList[1].BufferLength = 0;
-
- /* fill input */
- ObjType = ACL$C_FILE;
- Buffer = CHP$M_READ;
- UserNameDesc.dsc$w_length = strlen(UserName);
- UserNameDesc.dsc$b_dtype = DSC$K_DTYPE_T;
- UserNameDesc.dsc$b_class = DSC$K_CLASS_S;
- UserNameDesc.dsc$a_pointer = (char *)UserName;
- FileNameDesc.dsc$w_length = strlen(VmsName);
- FileNameDesc.dsc$b_dtype = DSC$K_DTYPE_T;
- FileNameDesc.dsc$b_class = DSC$K_CLASS_S;
- FileNameDesc.dsc$a_pointer = VmsName;
-
- /* call system */
- Result = sys$check_access(&ObjType,&FileNameDesc,&UserNameDesc,ItemList);
-
- if (Result == SS$_NORMAL)
- return(YES);
- else
- return(NO);
- }
-
- return(NO);
- }
-
-
-
- /* PUBLIC HTVMS_wwwName()
- ** CONVERTS VMS Name into WWW Name
- ** ON ENTRY:
- ** vmsname VMS file specification (NO NODE)
- **
- ** ON EXIT:
- ** returns www file specification
- **
- ** EXAMPLES:
- ** vmsname wwwname
- ** DISK$USER disk$user
- ** DISK$USER: /disk$user/
- ** DISK$USER:[DUNS] /disk$user/duns
- ** DISK$USER:[DUNS.ECHO] /disk$user/duns/echo
- ** [DUNS] duns
- ** [DUNS.ECHO] duns/echo
- ** [DUNS.ECHO.-.TRANS] duns/echo/../trans
- ** [DUNS.ECHO.--.TRANS] duns/echo/../../trans
- ** [.DUNS] duns
- ** [.DUNS.ECHO] duns/echo
- ** [.DUNS.ECHO]TEST.COM duns/echo/test.com
- ** TEST.COM test.com
- **
- **
- */
- PUBLIC char * HTVMS_wwwName ARGS1(
- char *, vmsname)
- {
- static char wwwname[256];
- char *src, *dst;
- int dir;
- dst = wwwname;
- src = vmsname;
- dir = 0;
- if (strchr(src,':')) *(dst++) = '/';
- for ( ; *src != '\0' ; src++)
- {
- switch(*src)
- {
- case ':': *(dst++) = '/'; break;
- case '-': if (dir)
- {
- if ((*(src-1)=='[' || *(src-1)=='.' || *(src-1)=='-') &&
- (*(src+1)=='.' || *(src+1)=='-'))
- {
- *(dst++) = '/';
- *(dst++) = '.';
- *(dst++) = '.';
- }
- else
- *(dst++) = '-';
- }
- else
- {
- if (*(src-1) == ']') *(dst++) = '/';
- *(dst++) = '-';
- }
- break;
- case '.': if (dir)
- {
- if (*(src-1) != '[') *(dst++) = '/';
- }
- else
- {
- if (*(src-1) == ']') *(dst++) = '/';
- *(dst++) = '.';
- }
- break;
- case '[': dir = 1; break;
- case ']': dir = 0; break;
- default: if (*(src-1) == ']') *(dst++) = '/';
- *(dst++) = *src;
- break;
- }
- }
- *(dst++) = '\0';
- return(wwwname);
- }
-
-
- /* PUBLIC HTVMS_name()
- ** CONVERTS WWW name into a VMS name
- ** ON ENTRY:
- ** nn Node Name (optional)
- ** fn WWW file name
- **
- ** ON EXIT:
- ** returns vms file specification
- **
- ** Bug: Returns pointer to static -- non-reentrant
- */
- PUBLIC char * HTVMS_name ARGS2(
- CONST char *, nn,
- CONST char *, fn)
- {
-
- /* We try converting the filename into Files-11 syntax. That is, we assume
- ** first that the file is, like us, on a VMS node. We try remote
- ** (or local) DECnet access. Files-11, VMS, VAX and DECnet
- ** are trademarks of Digital Equipment Corporation.
- ** The node is assumed to be local if the hostname WITHOUT DOMAIN
- ** matches the local one. @@@
- */
- static char vmsname[INFINITY]; /* returned */
- char * filename = (char*)malloc(strlen(fn)+1);
- char * nodename = (char*)malloc(strlen(nn)+2+1); /* Copies to hack */
- char *second; /* 2nd slash */
- char *last; /* last slash */
-
- char * hostname = (char *)HTHostName();
-
- if (!filename || !nodename) outofmem(__FILE__, "HTVMSname");
- strcpy(filename, fn);
- strcpy(nodename, ""); /* On same node? Yes if node names match */
- if (strncmp(nn,"localhost",9)) {
- char *p, *q;
- for (p=hostname, q=(char *)nn;
- *p && *p!='.' && *q && *q!='.'; p++, q++){
- if (TOUPPER(*p)!=TOUPPER(*q)) {
- strcpy(nodename, nn);
- q = strchr(nodename, '.'); /* Mismatch */
- if (q) *q=0; /* Chop domain */
- strcat(nodename, "::"); /* Try decnet anyway */
- break;
- }
- }
- }
-
- second = strchr(filename+1, '/'); /* 2nd slash */
- last = strrchr(filename, '/'); /* last slash */
-
- if (!second) { /* Only one slash */
- sprintf(vmsname, "%s%s", nodename, filename + 1);
- } else if(second==last) { /* Exactly two slashes */
- *second = 0; /* Split filename from disk */
- sprintf(vmsname, "%s%s:%s", nodename, filename+1, second+1);
- *second = '/'; /* restore */
- } else { /* More than two slashes */
- char * p;
- *second = 0; /* Split disk from directories */
- *last = 0; /* Split dir from filename */
- sprintf(vmsname, "%s%s:[%s]%s",
- nodename, filename+1, second+1, last+1);
- *second = *last = '/'; /* restore filename */
- for (p=strchr(vmsname, '['); *p!=']'; p++)
- if (*p=='/') *p='.'; /* Convert dir sep. to dots */
- }
- free(nodename);
- free(filename);
- return vmsname;
- }
-
- /*
- ** The code below is for directory browsing by VMS Curses clients.
- ** It is based on the newer WWWLib's HTDirBrw.c. - Foteos Macrides
- */
- PUBLIC int HTStat ARGS2(
- CONST char *, filename,
- stat_t *, info)
- {
- /*
- the following stuff does not work in VMS with a normal stat...
- --> /disk$user/duns/www if www is a directory
- is statted like: /disk$user/duns/www.dir
- after a normal stat has failed
- --> /disk$user/duns if duns is a toplevel directory
- is statted like: /disk$user/000000/duns.dir
- --> /disk$user since disk$user is a device
- is statted like: /disk$user/000000/000000.dir
- --> /
- searches all devices, no solution yet...
- --> /vxcern!/disk$cr/wwwteam/login.com
- is not statted but granted with fake information...
- */
- int Result;
- int Len;
- char *Ptr, *Ptr2;
- char Name[256];
-
- /* try normal stat... */
- Result = stat((char *)filename,info);
- if (Result == 0)
- return(Result);
-
- /* make local copy */
- strcpy(Name,filename);
-
- #ifdef NOT_USED
- /* if filename contains a node specification (! or ::), we will try to access
- the file via DECNET, but we do not stat it..., just return success
- with some fake information... */
- if (HTVMS_checkDecnet(Name))
- {
- /* set up fake info, only the one we use... */
- info->st_dev = NULL;
- info->st_ino[0] = 0;
- info->st_ino[1] = 0;
- info->st_ino[2] = 0;
- info->st_mode = S_IFREG | S_IREAD; /* assume it is a regular Readable file */
- info->st_nlink = NULL;
- info->st_uid = 0;
- info->st_gid = 0;
- info->st_rdev = 0;
- info->st_size = 0;
- info->st_atime = time(NULL);
- info->st_mtime = time(NULL);
- info->st_ctime = time(NULL);
-
- return(0);
- }
- #endif /* NOT_USED */
-
- /* failed,so do device search in case root is requested */
- if (!strcmp(Name,"/"))
- { /* root requested */
- return(-1);
- }
-
- /* failed so this might be a directory, add '.dir' */
- Len = strlen(Name);
- if (Name[Len-1] == '/')
- Name[Len-1] = '\0';
-
- /* fail in case of device */
- Ptr = strchr(Name+1,'/');
- if ((Ptr == NULL) && (Name[0] == '/'))
- { /* device only... */
- strcat(Name,"/000000/000000");
- }
-
- if (Ptr != NULL)
- { /* correct filename in case of toplevel dir */
- Ptr2 = strchr(Ptr+1,'/');
- if ((Ptr2 == NULL) && (Name[0] == '/'))
- {
- char End[256];
- strcpy(End,Ptr);
- *(Ptr+1) = '\0';
- strcat(Name,"000000");
- strcat(Name,End);
- }
- }
-
- /* try in case a file on toplevel directory or .DIR was alreadyt specified */
- Result = stat(Name,info);
- if (Result == 0)
- return(Result);
-
- /* add .DIR and try again */
- strcat(Name,".dir");
- Result = stat(Name,info);
- return(Result);
- }
-
- /*** "dirent.h" ***/
- #include <types.h>
-
- #ifndef _POSIX_SOURCE
- #define d_ino d_fileno /* compatability */
- #ifndef NULL
- #define NULL 0
- #endif
- #endif /* !_POSIX_SOURCE */
-
- typedef struct __dirdesc {
- #if 0
- int dd_fd; /* file descriptor */
- long dd_loc; /* buf offset of entry from last readddir() */
- long dd_size; /* amount of valid data in buffer */
- long dd_bsize; /* amount of entries read at a time */
- long dd_off; /* Current offset in dir (for telldir) */
- char *dd_buf; /* directory data buffer */
- #endif
- long context; /* context descriptor for LIB$FIND_FILE calls */
- char dirname[255+1]; /* keeps the directory name, including *.* */
- struct dsc$descriptor_s dirname_desc; /* descriptor of dirname */
- } DIR;
-
- extern DIR *opendir(char *dirname);
- extern struct dirent *readdir(DIR *dirp);
- extern int closedir(DIR *dirp);
- #if 0
- #ifndef _POSIX_SOURCE
- extern void seekdir(/* DIR *dirp, int loc */);
- extern long telldir(/* DIR *dirp */);
- #endif /* POSIX_SOURCE */
- extern void rewinddir(/* DIR *dirp */);
-
- #ifndef lint
- #define rewinddir(dirp) seekdir((dirp), (long)0)
- #endif
- #endif /* not defined for VMS */
-
- /*** #include "sys_dirent.h" ***/
- /*** "sys_dirent.h" ***/
- struct dirent {
- #if 0
- off_t d_off; /* offset of next disk dir entry */
- #endif
- unsigned long d_fileno; /* file number of entry */
- #if 0
- unsigned short d_reclen; /* length of this record */
- #endif
- unsigned short d_namlen; /* length of string in d_name */
- char d_name[255+1]; /* name (up to MAXNAMLEN + 1) */
- };
-
- #ifndef _POSIX_SOURCE
- /*
- * It's unlikely to change, but make sure that sizeof d_name above is
- * at least MAXNAMLEN + 1 (more may be added for padding).
- */
- #define MAXNAMLEN 255
- /*
- * The macro DIRSIZ(dp) gives the minimum amount of space required to represent
- * a directory entry. For any directory entry dp->d_reclen >= DIRSIZ(dp).
- * Specific filesystem types may use this macro to construct the value
- * for d_reclen.
- */
- #undef DIRSIZ
- #define DIRSIZ(dp) \
- (((sizeof(struct dirent) - (MAXNAMLEN+1) + ((dp)->d_namlen+1)) +3) & ~3)
-
- #endif /* !_POSIX_SOURCE */
-
-
- DIR *opendir(char *dirname)
- {
- static DIR dir;
- char *closebracket;
- long status;
- struct dsc$descriptor_s entryname_desc;
- struct dsc$descriptor_s dirname_desc;
- char DirEntry[256];
- char VMSentry[256];
- char UnixEntry[256];
- int index;
- char *dot;
-
- /* check if directory exists */
- /* dirname can look like /disk$user/duns/www/test/multi */
- /* or like /disk$user/duns/www/test/multi/ */
- /* DirEntry should look like disk$user:[duns.www.test]multi in both cases */
- /* dir.dirname should look like disk$user:[duns.www.test.multi] */
- strcpy(UnixEntry,dirname);
- if (UnixEntry[strlen(UnixEntry)-1] != '/')
- strcat(UnixEntry,"/");
-
- strcpy(DirEntry, HTVMS_name("",UnixEntry));
- strcpy(dir.dirname, DirEntry);
- index = strlen(DirEntry) - 1;
-
- if (DirEntry[index] == ']')
- DirEntry[index] = '\0';
-
- if ((dot = strrchr(DirEntry,'.')) == NULL)
- { /* convert disk$user:[duns] into disk$user:[000000]duns.dir */
- char *openbr = strrchr(DirEntry,'[');
- if (!openbr)
- { /* convert disk$user: into disk$user:[000000]000000.dir */
- strcpy(dir.dirname, DirEntry);
- strcat(dir.dirname, "[000000]");
- strcat(DirEntry,"[000000]000000.dir");
- }
- else
- {
- char End[256];
- strcpy(End,openbr+1);
- *(openbr+1) = '\0';
- strcat(DirEntry,"000000]");
- strcat(DirEntry,End);
- strcat(DirEntry,".dir");
- }
- }
- else
- {
- *dot = ']';
- strcat(DirEntry,".dir");
- }
-
- dir.context = 0;
- dirname_desc.dsc$w_length = strlen(DirEntry);
- dirname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
- dirname_desc.dsc$b_class = DSC$K_CLASS_S;
- dirname_desc.dsc$a_pointer = (char *)&(DirEntry);
-
- /* look for the directory */
- entryname_desc.dsc$w_length = 255;
- entryname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
- entryname_desc.dsc$b_class = DSC$K_CLASS_S;
- entryname_desc.dsc$a_pointer = VMSentry;
-
- status = lib$find_file(&(dirname_desc),
- &entryname_desc,
- &(dir.context),
- 0,0,0,0);
- if (!(status & 0x01))
- { /* directory not found */
- return(NULL);
- }
-
- #if 0
- /* now correct dirname, which looks like disk$user:[duns.www.test]multi */
- /* and should look like disk$user:[duns.www.test.multi] */
- closebracket = strchr(dir.dirname,']');
- *closebracket = '.';
- closebracket = strstr(dir.dirname,".dir");
- *closebracket = '\0';
- strcat(dir.dirname,"]");
- #endif
-
- if (HTVMSFileVersions)
- strcat(dir.dirname,"*.*;*");
- else
- strcat(dir.dirname,"*.*");
- dir.context = 0;
- dir.dirname_desc.dsc$w_length = strlen(dir.dirname);
- dir.dirname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
- dir.dirname_desc.dsc$b_class = DSC$K_CLASS_S;
- dir.dirname_desc.dsc$a_pointer = (char *)&(dir.dirname);
- return(&dir);
- }
-
- struct dirent *readdir(DIR *dirp)
- {
- static struct dirent entry;
- long status;
- struct dsc$descriptor_s entryname_desc;
- char *space, *slash;
- char VMSentry[256];
- char *UnixEntry;
-
- entryname_desc.dsc$w_length = 255;
- entryname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
- entryname_desc.dsc$b_class = DSC$K_CLASS_S;
- entryname_desc.dsc$a_pointer = VMSentry;
-
- status = lib$find_file(&(dirp->dirname_desc),
- &entryname_desc,
- &(dirp->context),
- 0,0,0,0);
- if (status == RMS$_NMF)
- { /* no more files */
- return(NULL);
- }
- else
- { /* ok */
- if (!(status & 0x01)) return(0);
- if (HTVMSFileVersions)
- space = strchr(VMSentry,' ');
- else
- space = strchr(VMSentry,';');
- if (space)
- *space = '\0';
-
- /* convert to unix style... */
- UnixEntry = HTVMS_wwwName(VMSentry);
- slash = strrchr(UnixEntry,'/') + 1;
- strcpy(entry.d_name,slash);
- entry.d_namlen = strlen(entry.d_name);
- entry.d_fileno = 1;
- return(&entry);
- }
- }
-
- int closedir(DIR *dirp)
- {
- long status;
-
- status = lib$find_file_end(&(dirp->context));
- if (!(status & 0x01)) exit(status);
- dirp->context = 0;
- return(0);
- }
-
- #include "HTAnchor.h"
- #include "HTParse.h"
- #include "HTBTree.h"
- #include "HTFile.h" /* For HTFileFormat() */
- #include "HTAlert.h"
- #define FREE(x) if (x) {free(x); x=NULL;}
- /*
- ** Hypertext object building machinery.
- */
- #include "HTML.h"
- #define PUTC(c) (*targetClass.put_character)(target, c)
- #define PUTS(s) (*targetClass.put_string)(target, s)
- #define START(e) (*targetClass.start_element)(target, e, 0, 0)
- #define END(e) (*targetClass.end_element)(target, e)
- #define FREE_TARGET (*targetClass._free)(target)
- #define ABORT_TARGET (*targetClass._free)(target)
- struct _HTStructured {
- CONST HTStructuredClass * isa;
- /* ... */
- };
-
- #define STRUCT_DIRENT struct dirent
-
- PRIVATE char * months[12] = {
- "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
- };
-
- typedef struct _VMSEntryInfo {
- char * filename;
- char * type;
- char * date;
- unsigned int size;
- BOOLEAN display; /* show this entry? */
- } VMSEntryInfo;
-
- PRIVATE void free_VMSEntryInfo_struct_contents ARGS1(VMSEntryInfo *,entry_info)
- {
- if(entry_info) {
- if(entry_info->filename) free(entry_info->filename);
- if(entry_info->type) free(entry_info->type);
- if(entry_info->date) free(entry_info->date);
- }
- /* dont free the struct */
- }
-
- #define FILE_BY_NAME 0
- #define FILE_BY_TYPE 1
- #define FILE_BY_SIZE 2
- #define FILE_BY_DATE 3
- extern BOOLEAN HTfileSortMethod; /* specifies the method of sorting */
-
- PUBLIC int compare_VMSEntryInfo_structs ARGS2(VMSEntryInfo *,entry1,
- VMSEntryInfo *,entry2)
- {
- int status;
-
- switch(HTfileSortMethod)
- {
- case FILE_BY_SIZE:
- /* both equal or both 0 */
- if(entry1->size == entry2->size)
- return(strcasecomp(entry1->filename,
- entry2->filename));
- else
- if(entry1->size > entry2->size)
- return(1);
- else
- return(-1);
- break;
- case FILE_BY_TYPE:
- if(entry1->type && entry2->type) {
- status = strcasecomp(entry1->type, entry2->type);
- if(status)
- return(status);
- /* else fall to filename comparison */
- }
- return (strcasecomp(entry1->filename,
- entry2->filename));
- break;
- case FILE_BY_DATE:
- if(entry1->date && entry2->date) {
- /* We really should change the type :( */
- status = strcasecomp(entry1->date, entry2->date);
- if(status)
- return(status);
- /* else fall to filename comparison */
- }
- return (strcasecomp(entry1->filename,
- entry2->filename));
- break;
- case FILE_BY_NAME:
- default:
- return (strcasecomp(entry1->filename,
- entry2->filename));
- }
- }
-
-
- /* HTVMSBrowseDir()
- **
- ** This function generates a directory listing as an HTML-object
- ** for local file URL's. It assumes the first two elements of
- ** of the path are a device followed by a directory:
- **
- ** file://localhost/device/directory[/[foo]]
- **
- ** Will not accept 000000 as a directory name.
- ** Will offer links to parent through the top directory, unless
- ** a terminal slash was included in the calling URL.
- **
- ** Returns HT_LOADED on success, HTLoadError() messages on error.
- **
- ** Developed for Lynx by Foteos Macrides (macrides@sci.wfeb.edu).
- */
- PUBLIC int HTVMSBrowseDir ARGS4(
- CONST char *, address,
- HTParentAnchor *, anchor,
- HTFormat, format_out,
- HTStream *, sink
- )
- {
- HTStructured* target;
- HTStructuredClass targetClass;
- char *pathname = HTParse(address, "", PARSE_PATH + PARSE_PUNCTUATION);
- char *tail = NULL;
- char *title = NULL;
- char *header = NULL;
- char *parent = NULL;
- char *relative = NULL;
- char *cp, *cp1;
- int pathend;
- DIR *dp;
- struct stat file_info;
- time_t NowTime;
- static char ThisYear[8];
- VMSEntryInfo *entry_info=0;
- char string_buffer[64];
- extern BOOLEAN nodotfiles;
-
- CTRACE(stderr,"HTVMSBrowseDir: Browsing `%s\'\n", pathname);
-
- /*
- * Require at least two elements (presumably a device and directory)
- * and disallow the device root (000000 directory). Symbolic paths
- * (e.g., sys$help) should have been translated and expanded (e.g.,
- * to /sys$sysroot/syshlp) before calling this routine.
- */
- if (((*pathname != '/') ||
- (cp=strchr(pathname+1, '/')) == NULL ||
- *(cp+1) == '\0' ||
- 0==strncmp((cp+1), "000000", 6)) ||
- (dp=opendir(pathname)) == NULL) {
- FREE(pathname);
- return HTLoadError(sink, 403, "Could not access directory.");
- }
-
- /*
- * Set up the output stream.
- */
- _HTProgress ("Building directory listing...");
- target = HTML_new(anchor, format_out, sink);
- targetClass = *(target->isa);
-
- /*
- * Set up the offset string of the anchor reference,
- * and strings for the title and header.
- */
- cp = strrchr(pathname, '/'); /* find lastslash */
- StrAllocCopy(tail, (cp+1)); /* take slash off the beginning */
- if (*tail != '\0') {
- StrAllocCopy(title, tail);
- *cp = '\0';
- if ((cp1=strrchr(pathname, '/')) != NULL &&
- cp1 != pathname &&
- strncmp((cp1+1), "000000", 6))
- StrAllocCopy(parent, (cp1+1));
- *cp = '/';
- } else {
- pathname[strlen(pathname)-1] = '\0';
- cp = strrchr(pathname, '/');
- StrAllocCopy(title, (cp+1));
- pathname[strlen(pathname)] = '/';
- }
- StrAllocCopy(header, pathname);
-
- /*
- * Initialize path name for HTStat().
- */
- pathend = strlen(pathname);
- if (*(pathname+pathend-1) != '/') {
- StrAllocCat(pathname, "/");
- pathend++;
- }
-
- /*
- * Output the title and header.
- */
- START(HTML_HTML);
- PUTS("\n");
- START(HTML_HEAD);
- PUTS("\n");
- HTUnEscape(title);
- START(HTML_TITLE);
- PUTS(title);
- PUTS(" directory");
- END(HTML_TITLE);
- PUTS("\n");
- FREE(title);
- END(HTML_HEAD);
- PUTS("\n");
- START(HTML_BODY);
- PUTS("\n");
- HTUnEscape(header);
- START(HTML_H1);
- PUTS(header);
- END(HTML_H1);
- PUTS("\n");
- if (HTDirReadme == HT_DIR_README_TOP) {
- FILE * fp;
- if (header[strlen(header)-1] != '/')
- StrAllocCat(header, "/");
- StrAllocCat(header, HT_DIR_README_FILE);
- if ((fp = fopen(header, "r")) != NULL) {
- START(HTML_PRE);
- for(;;) {
- char c = fgetc(fp);
- if (c == (char)EOF) break;
- switch (c) {
- case '&':
- case '<':
- case '>':
- PUTC('&');
- PUTC('#');
- PUTC((char)(c / 10));
- PUTC((char) (c % 10));
- PUTC(';');
- break;
- default:
- PUTC(c);
- }
- }
- END(HTML_PRE);
- fclose(fp);
- }
- }
- FREE(header);
- if (parent) {
- relative = (char*) malloc(strlen(tail) + 4);
- if (relative == NULL)
- outofmem(__FILE__, "HTVMSBrowseDir");
- sprintf(relative, "%s/..", tail);
- HTStartAnchor(target, "", relative);
- PUTS("Up to ");
- HTUnEscape(parent);
- PUTS(parent);
- END(HTML_A);
- START(HTML_P);
- PUTS("\n");
- FREE(relative);
- FREE(parent);
- }
-
- /*
- * Set up the date comparison.
- */
- NowTime = time(NULL);
- strcpy(ThisYear, (char *)ctime(&NowTime)+20);
- ThisYear[4] = '\0';
-
- /*
- * Now, generate the Btree and put it out to the output stream.
- */
- {
- char dottest = 2; /* To avoid two strcmp() each time */
- STRUCT_DIRENT *dirbuf;
- HTBTree *bt;
-
- /* Set up sort key and initialize BTree */
- bt = HTBTree_new((HTComparer) compare_VMSEntryInfo_structs);
-
- /* Build tree */
- while ((dirbuf = readdir(dp))) {
- HTAtom *encoding = NULL;
- HTFormat format;
-
- /* Skip if not used */
- if (!dirbuf->d_ino) {
- continue;
- }
-
- /* Current and parent directories are never shown in list */
- if (dottest && (!strcmp(dirbuf->d_name, ".") ||
- !strcmp(dirbuf->d_name, ".."))) {
- dottest--;
- continue;
- }
-
- /* Don't show the selective enabling file
- * unless version numbers are included */
- if (!strcasecomp(dirbuf->d_name, HT_DIR_ENABLE_FILE)) {
- continue;
- }
-
- /* Skip files beginning with a dot? */
- if (nodotfiles && *dirbuf->d_name == '.') {
- continue;
- }
-
- /* OK, make an lstat() and get a key ready. */
- *(pathname+pathend) = '\0';
- StrAllocCat(pathname, dirbuf->d_name);
- if (HTStat(pathname, &file_info)) {
- /* for VMS the failure here means the file is not readable...
- we however continue to browse through the directory... */
- continue;
- }
- entry_info = (VMSEntryInfo *)malloc(sizeof(VMSEntryInfo));
- if (entry_info == NULL)
- outofmem(__FILE__, "HTVMSBrowseDir");
- entry_info->type = 0;
- entry_info->size = 0;
- entry_info->date = 0;
- entry_info->filename = 0;
- entry_info->display = TRUE;
-
- /* Get the type */
- format = HTFileFormat(dirbuf->d_name, &encoding);
- if(!strncmp(HTAtom_name(format), "application",11))
- {
- cp = HTAtom_name(format) + 12;
- if(!strncmp(cp,"x-",2))
- cp+=2;
- }
- else
- cp = HTAtom_name(format);
- StrAllocCopy(entry_info->type, cp);
-
- StrAllocCopy(entry_info->filename, dirbuf->d_name);
- if ((file_info.st_mode & S_IFMT) == S_IFDIR) {
- /* strip .DIR part... */
- char *dot;
- dot = strstr(entry_info->filename, ".DIR");
- if (dot)
- *dot = '\0';
- StrAllocCopy(entry_info->type, "Directory");
- }
-
- /* Get the date */
- {
- char *t = (char *)ctime((CONST time_t *)&file_info.st_ctime);
- *(t+24) = '\0';
-
- StrAllocCopy(entry_info->date, (t+4));
- *((entry_info->date)+7) = '\0';
- if ((atoi((t+19))) < atoi(ThisYear))
- StrAllocCat(entry_info->date, (t+19));
- else {
- StrAllocCat(entry_info->date, (t+11));
- *((entry_info->date)+12) = '\0';
- }
- }
-
- /* Get the size */
- if ((file_info.st_mode & S_IFMT) != S_IFDIR)
- entry_info->size = (unsigned int)file_info.st_size;
- else
- entry_info->size = 0;
-
- /* Now, update the BTree etc. */
- if(entry_info->display)
- {
- CTRACE(stderr,"Adding file to BTree: %s\n",
- entry_info->filename);
- HTBTree_add(bt, (VMSEntryInfo *)entry_info);
- }
-
- } /* End while readdir() */
-
- FREE(pathname);
- closedir(dp);
-
- START(HTML_PRE);
- /*
- * Run through the BTree printing out in order
- */
- {
- HTBTElement * ele;
- int i;
- for (ele = HTBTree_next(bt, NULL);
- ele != NULL;
- ele = HTBTree_next(bt, ele))
- {
- entry_info = (VMSEntryInfo *)HTBTree_object(ele);
-
- /* Output the date */
- if(entry_info->date)
- {
- PUTS(entry_info->date);
- PUTS(" ");
- }
- else
- PUTS(" * ");
-
- /* Output the type */
- if(entry_info->type)
- {
- for(i = 0; entry_info->type[i] != '\0' && i < 15; i++)
- PUTC(entry_info->type[i]);
- for(; i < 17; i++)
- PUTC(' ');
-
- }
-
- /* Output the link for the name */
- HTDirEntry(target, tail, entry_info->filename);
- PUTS(entry_info->filename);
- END(HTML_A);
-
- /* Output the size */
- if(entry_info->size)
- {
- if(entry_info->size < 1024)
- sprintf(string_buffer," %d bytes",
- entry_info->size);
- else
- sprintf(string_buffer," %dKb",
- entry_info->size/1024);
- PUTS(string_buffer);
- }
-
- PUTC('\n'); /* end of this entry */
-
- free_VMSEntryInfo_struct_contents(entry_info);
- }
- }
-
- HTBTreeAndObject_free(bt);
-
- } /* End of both BTree loops */
-
- /*
- * Complete the output stream.
- */
- END(HTML_PRE);
- PUTS("\n");
- END(HTML_BODY);
- PUTS("\n");
- END(HTML_HTML);
- PUTS("\n");
- FREE(tail);
- FREE_TARGET;
-
- return HT_LOADED;
-
- } /* End of directory reading section */
-